//package com.frame.common.core.security.config;
//
//import com.fasterxml.jackson.databind.ObjectMapper;
//import com.frame.common.core.security.LoginDTO;
//import com.frame.common.core.security.entity.SecurityUser;
//import com.frame.common.core.security.utils.TokenUtil;
//import com.frame.common.exception.CustomAuthenticationException;
//import com.frame.common.utils.R;
//import com.frame.common.utils.ResponseUtil;
//import com.frame.common.constans.ResultCode;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.data.redis.core.RedisTemplate;
//import org.springframework.security.authentication.AuthenticationManager;
//import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
//import org.springframework.security.core.Authentication;
//import org.springframework.security.core.AuthenticationException;
//import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
//
//import javax.servlet.FilterChain;
//import javax.servlet.ServletException;
//import javax.servlet.http.HttpServletRequest;
//import javax.servlet.http.HttpServletResponse;
//import java.io.IOException;
//import java.util.ArrayList;
//import java.util.Set;
//
//@Slf4j
//public class UsernamePasswordLoginFilter extends UsernamePasswordAuthenticationFilter {
//
//    private AuthenticationManager authenticationManager;
//    private TokenUtil tokenUtil;
//    private RedisTemplate redisTemplate;
//
//
//    public UsernamePasswordLoginFilter(TokenUtil tokenUtil,
//                                       RedisTemplate redisTemplate,
//                                       AuthenticationManager authenticationManager) {
//        this.authenticationManager = authenticationManager;
//        this.tokenUtil = tokenUtil;
//        this.redisTemplate = redisTemplate;
//        //是否只允许post请求，如果是true的话，其他请求进来会报错，跟没有授权一样的效果
//        this.setPostOnly(false);
//        //设置登录表单的提交action和请求类型
////        this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/login", "POST"));
//    }
//
//    /**
//     * 登录认证方法
//     *
//     * @param request
//     * @param response
//     * @return
//     * @throws AuthenticationException
//     */
//    @Override
//    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
//        try {
//            LoginDTO loginDTO = new ObjectMapper().readValue(request.getInputStream(), LoginDTO.class);
//            //该方法尝试对传递的 Authentication 对象进行认证
//            return authenticationManager.authenticate(
//                    //此方法是Authentication的子类，会将认证状态设置为true，而下面那个构造方法并不会设置认证状态为true。
//                    //此方法后面的那个列表是权限列表，因为我们是要从数据库查询权限的，所以这里设置为空列表。即使设置了，在userDetail返回数据的时候也会被冲掉
//                    new UsernamePasswordAuthenticationToken(loginDTO.getUsername(), loginDTO.getPassword(), new ArrayList<>()));
//            //new UsernamePasswordAuthenticationToken(loginDTO.username,loginDTO.password));
//        } catch (IOException e) {
//            log.error("认证失败",e);
//            throw new CustomAuthenticationException(ResultCode.USER_AUTHORIZED_NO_SUCCESS.getMessage());
//        }
//    }
//
//    /**
//     * 登录认证成功
//     *
//     * @param request
//     * @param response
//     * @param chain
//     * @param authResult
//     * @throws IOException
//     * @throws ServletException
//     */
//    @Override
//    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
//        //认证方法调用userDetails,自定义userDetailService返回的对象是UserByUserDetail，所以这里当然也是用这个对象接收
//        SecurityUser securityUser = (SecurityUser) authResult.getPrincipal();
//
//        //将用户权限写入redis
//        Set<String> permissionValueList = securityUser.getPermissions();
//        String permissionKey = TokenUtil.getRedisKey(securityUser.getUsername());
//        redisTemplate.opsForValue().set(permissionKey, permissionValueList);
//
//        //创建token
//        String token = tokenUtil.createToken(securityUser.getUsername());
//        ResponseUtil.out(response, R.success(token));
//    }
//
//    /**
//     * 登录认证失败
//     *
//     * @param request
//     * @param response
//     * @param failed
//     * @throws IOException
//     * @throws ServletException
//     */
//    @Override
//    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
//        ResponseUtil.out(response, R.error(ResultCode.USER_LOGIN_ERROR));
//    }
//}